Skip to content

Conversation

@tejasbadadare
Copy link
Contributor

@tejasbadadare tejasbadadare commented Apr 23, 2025

Summary

Optimize gas usage when querying for all active subscriptions.

Rationale

This is one the most frequent access patterns in scheduler, since keepers need to poll the set of active subscriptions periodically to keep their state consistent. It's a view function so it will just be simulated, but since we could potentially store thousands of subscriptions, we still want to make it efficient.

This optimization sacrifices a bit of gas when activating/deactivating subscriptions (which should be relatively uncommon), for efficiency gains in the getActiveSubscriptions function. Previously we needed to iterate through all subscriptions to collect the active ones. This doesn't scale well as more subscriptions get deactivated.

Now, we store the active subscriptions in an activeSubscriptionIds array for efficient querying and paging, and store a map of sub id -> index in activeSubscriptionIds for efficient removal when deactivating subscriptions.

How has this been tested?

  • Current tests cover my changes
  • Added new tests
  • Manually tested the code

Gas benchmark results

Test case Original gas Optimized gas Delta
Query 5 active subscriptions (out of 10) 110,317 82,547 -25%
Query 50 active subscriptions (out of 100) 1,104,981 818,371 -26%
Query 500 active subscriptions (out of 1000) 16,622,552 13,747,542 -17%

@vercel
Copy link

vercel bot commented Apr 23, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

6 Skipped Deployments
Name Status Preview Comments Updated (UTC)
api-reference ⬜️ Ignored (Inspect) Visit Preview Apr 23, 2025 6:04pm
component-library ⬜️ Ignored (Inspect) Visit Preview Apr 23, 2025 6:04pm
entropy-debugger ⬜️ Ignored (Inspect) Visit Preview Apr 23, 2025 6:04pm
insights ⬜️ Ignored (Inspect) Visit Preview Apr 23, 2025 6:04pm
proposals ⬜️ Ignored (Inspect) Visit Preview Apr 23, 2025 6:04pm
staking ⬜️ Ignored (Inspect) Visit Preview Apr 23, 2025 6:04pm

Copy link
Collaborator

@ali-behjati ali-behjati left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume we are sacrificing order to achieve linear removal and pagination; right? I'm fine with it. Just make sure to add documentation to the active subscription query that start index is not the subscription id.

_state.activeSubscriptionIds.push(subscriptionId);
_state.activeSubscriptionIndex[subscriptionId] = _state
.activeSubscriptionIds
.length;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe leave a comment here noting that this array is 1-indexed. I thought this was a bug until i looked further

that said, is there a test that adds & removes a bunch of subscriptions to validate that this logic works?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, the 1-based indexing is documented in other places, but it's definitely not intuitive so i'll mention it every place the map is directly used

There are tests that cover adding and removing subscriptions, and the gas benchmark adds and removes hundreds. I'll augment the existing unit tests to stress test the implementation some more.

@tejasbadadare tejasbadadare merged commit ff06b5e into main Apr 23, 2025
4 of 10 checks passed
@tejasbadadare tejasbadadare deleted the tb/pulse-scheduler/optimize-gas-active-subscriptions branch April 23, 2025 18:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants